package br.cns.metrics;

import org.apache.commons.math3.linear.Array2DRowRealMatrix;
import org.apache.commons.math3.linear.EigenDecomposition;
import org.apache.commons.math3.linear.RealMatrix;

import br.cns.Metric;
import br.cns.TMetric;
import br.cns.transformations.Laplacian;

public class AlgebraicConnectivity implements Metric {
	private static final AlgebraicConnectivity instance = new AlgebraicConnectivity();

	private AlgebraicConnectivity() {
	}

	public static AlgebraicConnectivity getInstance() {
		return instance;
	}

	public double calculate(int[][] matrix) {
		int[][] laplacian = Laplacian.getInstance().transform(matrix);
		double[][] realValues = new double[matrix.length][matrix.length];
		for (int i = 0; i < matrix.length; i++) {
			for (int j = 0; j < matrix[i].length; j++) {
				realValues[i][j] = laplacian[i][j];
			}
		}
		try {
			RealMatrix rm = new Array2DRowRealMatrix(realValues);
			EigenDecomposition solver = new EigenDecomposition(rm, 0);
			double[] autovalores = solver.getRealEigenvalues();
			double aux;
			for (int i = 0; i < autovalores.length; i++) {
				for (int j = i; j < autovalores.length; j++) {
					if (autovalores[j] < autovalores[i]) {
						aux = autovalores[i];
						autovalores[i] = autovalores[j];
						autovalores[j] = aux;
					}
				}
			}
			return autovalores[1];
		} catch (Exception e) {
			return 0;
		}
	}

	@Override
	public String name() {
		return TMetric.ALGEBRAIC_CONNECTIVITY.toString();
	}
}
